<template>
	<view class="wrapper">
		<view class="table-wrap" id="wrapper">
			<table class="custom-table">
				<tr>
					<th colspan="12" class="title">全屋智能设备清单空间汇总方案</th>
				</tr>
				<tr>
					<td class="label" colspan="3">客户姓名</td>
					<td class="value" colspan="9">{{ formData.customName || '' }}</td>
				</tr>
				<tr>
					<td class="label" colspan="3">客户地址</td>
					<td colspan="9" class="value">
						{{ formData.customAddress || '' }}
					</td>
				</tr>
				<tr>
					<td class="label" colspan="3">客户电话</td>
					<td class="value" colspan="9">
						{{ formData.customPhone || '' }}
					</td>
				</tr>
				<tr>
					<th class="label" colspan="2">产品类别</th>
					<th class="label" colspan="2">单价</th>
					<th class="label" colspan="2">数量</th>
					<th class="label" colspan="2">总价</th>
					<th class="label" colspan="2">实物图</th>
					<th class="label" colspan="2">供应商</th>
				</tr>
				<tr v-for="item in getMergedMaterialList()" :key="item.category">
					<td colspan="2" class="">{{ item.name }}</td>
					<td colspan="2" class="">{{ item.price.toFixed(2) }}</td>
					<td colspan="2" class="">{{ item.number }}</td>
					<td colspan="2" class="">{{ item.total.toFixed(2) }}</td>
					<td colspan="2">
						<image :src="imageBase64Map[item.category]" mode="aspectFit" />
					</td>
					<td colspan="2" class="">{{ item.supplier }}</td>
				</tr>
				<!-- 其它空间同理 -->
				<tr>
					<td class="label" colspan="8">全屋总价</td>
					<td class="value center" colspan="1">
						{{
							formData.list
								.reduce((allSum, item) => {
									return (
										allSum +
										item.list.reduce((sum, it) => {
											const price = parseFloat(
												categoryPriceList.find((f) => f.value === it.category)
													?.text || '0'
											)
											return sum + parseInt((it.number || 0) + '') * price
										}, 0)
									)
								}, 0)
								.toFixed(2)
						}}
					</td>
					<td class="label" colspan="2">优惠金额</td>
					<td class="value center" colspan="2">
						{{ parseFloat((formData.discount || 0) + '').toFixed(2) }}
					</td>
				</tr>
				<tr>
							
							
					<td class="label" colspan="6">安装调试费</td>
							
					<td class="value center" colspan="6">
						{{ parseFloat((formData.installPrice || 0) + '').toFixed(2) }}
					</td>
				</tr>
				<tr>
					<td class="label" colspan="8">
						全屋总价（含方案、产品、安装、调试、售后）为：
					</td>
					<td class="value center" colspan="4">
						{{
							(
								formData.list.reduce((allSum, item) => {
									return (
										allSum +
										item.list.reduce((sum, it) => {
											const price = parseFloat(
												categoryPriceList.find((f) => f.value === it.category)
													?.text || '0'
											)
											return sum + parseInt((it.number || 0) + '') * price
										}, 0)
									)
								}, 0) - parseFloat((formData.discount || 0) + '')+parseFloat((formData.installPrice || 0) + '')
							).toFixed(2)
						}}
					</td>
				</tr>
				<tr>
					<td colspan="12" class="note">
						备注：<br />
						1、报价单价格根据方案产品报价，最终成交价格以客户实际使用产品为准，采用客户未同意产品进行变相涨价等由我方承担责任。<br />
						2、为保障双方权益，双方达成一致后，预缴80%总价作为采购成本，产品上门安装调试验收合格后补齐20%尾款。<br />
						3、根据产品特性不同，智能开关保修期1年，智能传感器保修期2年，智能窗帘电机保修期5年。人为损坏不保修。<br />
						4、客户需提前预留开关零线和电动窗帘插座。如无，需及时沟通并做方案修改。
					</td>
				</tr>
			</table>
		</view>
		<button @click="canvasToImage.generateImage">下载</button>
	</view>
</template>
<script>
// import jsPDF from 'jspdf'
export default {
	components: {},
	data() {
		return {
			formData: {
				planName: '',
				customName: '',
				customPhone: '',
				customAddress: '',
				discount: 0,
				list: [
					{
						name: '',
						list: [],
						total: 0,
						id: new Date().getTime().toString()
					}
				]
			},
			imageBase64Map: {},
			featureId: [],
			spaceList: [],
			categoryList: [],
			categoryPriceList: [],
			secondCategoryList: [],
			featureList: [],
			firstIndex: 0,
			secondIndex: 0,
			rules: {
				planName: {
					rules: [
						{
							required: true,
							errorMessage: '请输入方案名'
						}
					]
				},
				customName: {
					rules: [
						{
							required: true,
							errorMessage: '请输入客户姓名'
						}
					]
				},
				customPhone: {
					rules: [
						{
							required: true,
							errorMessage: '请输入客户电话'
						}
					]
				},
				customAddress: {
					rules: [
						{
							required: true,
							errorMessage: '请输入客户地址'
						}
					]
				}
			}
		}
	},
	methods: {
		getImg(categoryId) {
			return this.categoryList.find((f) => f.value === categoryId).image
		},
		getMergedMaterialList() {
			const merged = {}
			this.formData.list.forEach((space) => {
				;(space.list || []).forEach((item) => {
					const key = item.category
					const price = parseFloat(
						this.categoryPriceList.find((f) => f.value === item.category)
							?.text || '0'
					)
					if (!merged[key]) {
						merged[key] = {
							category: item.category,
							name: this.categoryList.find((f) => f.value === item.category)
								?.text,
							price: price,
							number: 0,
							total: 0,
							image: this.imageBase64Map[item.category],
							supplier:  this.categoryList.find((f) => f.value === item.category)
								?.supplier
						
						}
					}
					merged[key].number += parseInt((item.number || 0) + '')
					merged[key].total += parseInt((item.number || 0) + '') * price
				})
			})
			console.log("==",merged)
			// Step 1: 将数据转换为数组（方便排序）
			const dataArray = Object.entries(merged).map(([id, item]) => ({
			    id,
			    ...item,
			    supplier: item.supplier || "" // 处理缺失的 supplier
			}));
			
			// Step 2: 按 supplier 排序
			dataArray.sort((a, b) => a.supplier.localeCompare(b.supplier));
			
			// Step 3: 重新转换为对象（保持原格式）
			const sortedData = {};
			dataArray.forEach(item => {
			    const { id, ...rest } = item;
			    sortedData[id] = rest;
			});
			return Object.values(sortedData)
		},
		getData() {
			const content = uni.getStorageSync('space_list_key')
			if (content) {
				this.spaceList = JSON.parse(content).map((m) => {
					return {
						value: m.id,
						text: m.name
					}
				})
			}
			const secondCategoryList = uni.getStorageSync('second_category_list_key')
			if (secondCategoryList) {
				this.secondCategoryList = JSON.parse(secondCategoryList).map((m) => {
					return {
						value: m.id,
						text: m.name
					}
				})
			}
			const feature = uni.getStorageSync('feature_list_key')
			if (feature) {
				this.featureList = JSON.parse(feature).map((m) => {
					return {
						id: m.id,
						name: m.name
					}
				})
			}
			const category = uni.getStorageSync('category_list_key')
			if (category) {
				this.categoryList = JSON.parse(category).map((m) => {
					return {
						value: m.id,
						text: m.name,
						image: m.image,
						supplier: m.supplier
					}
				})
				const that = this
				this.categoryList.forEach((cat) => {
					if (cat.image) {
						// this.imageUrlToBase64(cat.image, (base64) => {
						// 	this.$set(this.imageBase64Map, cat.value, base64)
						// })
						// plus.io.getImageInfo({
						// 	src: cat.image,
						// 	success: (res) => {
						// 		console.log(res)
						// 		const base64 = 'data:image/png;base64,' + res.base64
						// 		// use base64 as image src
						// 		this.$set(this.imageBase64Map, cat.value, base64)
						// 	},
						// 	fail: (err) => {
						// 		console.log(err)
						// 	}
						// })
						// const that = this
						// plus.io.requestFileSystem(
						// 	plus.io.PUBLIC_DOWNLOADS,
						// 	function (fs) {
						// 		fs.root.getFile(
						// 			'方案.txt',
						// 			{ create: false },
						// 			function (fileEntry) {
						// 				console.log(fileEntry.fullPath)
						// 				fileEntry.file(function (file) {
						// 					var reader = new plus.io.FileReader()
						// 					reader.onloadend = function (e) {
						// 						console.log(JSON.parse(e.target.result))
						// 						uni.setStorageSync(
						// 							'plan_list_key',
						// 							JSON.parse(e.target.result)
						// 						)
						// 						uni.showToast({
						// 							title: '导入成功',
						// 							icon: 'success',
						// 							duration: 2000
						// 						})
						// 						that.getData()
						// 					}
						// 					reader.readAsText(file)
						// 				})
						// 			},
						// 			function (err) {
						// 				console.log('failed:' + err)
						// 				plus.nativeUI.closeWaiting()
						// 			}
						// 		)
						// 	},
						// 	function (err) {
						// 		console.log(err)
						// 		plus.nativeUI.closeWaiting()
						// 	}
						// )
						plus.io.resolveLocalFileSystemURL(
							cat.image,
							function (entry) {
								// 可通过entry对象操作test.html文件
								console.log('entry:' + entry)
								entry.file(function (file) {
									console.log('file:' + JSON.stringify(file))
									var fileReader = new plus.io.FileReader()
									// alert('getFile:' + JSON.stringify(file))
									// fileReader.readAsText(file, 'utf-8')
									fileReader.onloadend = function (e) {
										that.$set(that.imageBase64Map, cat.value, e.target.result)
									}
									fileReader.readAsDataURL(file)
									// fileReader.onloadend = function (evt) {
									// 	alert('11' + evt)
									// 	alert('evt.target' + evt.target)
									// 	alert(evt.target.result)
									// }
									// alert(file.size + '--' + file.name)
								})
							},
							function (e) {
								alert('Resolve file URL failed: ' + e.message)
							}
						)
					}
				})
				this.categoryPriceList = JSON.parse(category).map((m) => {
					return {
						value: m.id,
						text: m.price
					}
				})
			}
		},
		base64ToByteArray(base64Str) {
			const binaryString = atob(base64Str)
			const uint8Array = new Uint8Array(binaryString.length)

			for (let i = 0; i < binaryString.length; i++) {
				uint8Array[i] = binaryString.charCodeAt(i)
			}
			let arr = []
			Array.from(uint8Array).map((num) => {
				arr.push(num >= 128 ? num - 256 : num)
			})
			return arr
		},

		downloadFile(data) {
			const fileName = (this.formData.planName || '方案') + '_物料清单.pdf'
			var index = data.indexOf(',')
			var base64Str = data.slice(index + 1, data.length)
			const that = this
			plus.io.requestFileSystem(plus.io.PUBLIC_DOWNLOADS, (fs) => {
				fs.root.getFile(fileName, { create: true }, (entry) => {
					var fullPath = entry.fullPath
					var Base64 = plus.android.importClass('android.util.Base64')
					var FileOutputStream = plus.android.importClass(
						'java.io.FileOutputStream'
					)
					var out = new FileOutputStream(fullPath)
					// 此处Base64.decode有长度限制，如果不能满足需求，可以考虑换成官方原生插件市场的【Base64转文件】
					// var bytes = Base64.decode(base64Str, Base64.DEFAULT);
					//转成Array避免长度限制
					let bytes = that.base64ToByteArray(base64Str)
					out.write(bytes)
					setTimeout(() => {
						uni.showToast({ title: '导出成功', icon: 'success' })
						plus.nativeUI.confirm(
							'下载成功, 是否打开文件',
							function (e) {
								var index = e.index
								if (index == 0) {
									plus.runtime.openFile(entry.fullPath)
								}
							},
							{
								title: '文件',
								buttons: ['是', '否'],
								verticalAlign: 'center'
							}
						)
					}, 2000)
					out.close()

					// entry.createWriter((writer) => {
					// 	writer.onwrite = (e) => {
					// 		uni.showToast({ title: '导出成功', icon: 'success' })
					// 		plus.nativeUI.confirm(
					// 			'下载成功, 是否打开文件',
					// 			function (e) {
					// 				var index = e.index
					// 				if (index == 0) {
					// 					plus.runtime.openFile(entry.fullPath)
					// 				}
					// 			},
					// 			{
					// 				title: '文件',
					// 				buttons: ['是', '否'],
					// 				verticalAlign: 'center'
					// 			}
					// 		)
					// 	}
					// 	writer.onerror = (e) => {
					// 		uni.showToast({ title: '导出失败', icon: 'none' })
					// 	}
					// 	writer.write(data)
					// })
				})
			})
		},
		getFeatureName(ids) {
			if (ids) {
				const arr = []
				ids.forEach((f) => {
					arr.push(this.featureList.find((d) => d.id === f)?.name || '')
				})
				return arr.join('/')
			}
		},
		imageUrlToBase64(url, callback) {
			const img = new Image()
			img.setAttribute('crossOrigin', 'anonymous')
			img.onload = function () {
				const canvas = document.createElement('canvas')
				canvas.width = img.width
				canvas.height = img.height
				const ctx = canvas.getContext('2d')
				ctx.drawImage(img, 0, 0, img.width, img.height)
				const dataURL = canvas.toDataURL('image/png')
				callback(dataURL)
			}
			img.src = url
		},
		getPrice() {
			let total = 0
			this.formData.list.forEach((f) => {
				f.list.forEach((d) => {
					if (d.number && d.category) {
						total +=
							parseInt((it.number || 0) + '') *
							parseFloat(
								this.categoryPriceList.find((f) => f.value === d.category)
									?.text || '0'
							)
					}
				})
			})
			if (this.formData.discount) {
				total -= parseInt((this.formData.discount || 0) + '')
			}
			return total
		}
	},
	onLoad(e) {
		if (e.data) {
			this.formData = JSON.parse(decodeURIComponent(e.data))
		}
		console.log(this.formData)
		this.getData()
		plus.screen.lockOrientation('landscape-primary')
	},
	onUnload() {
		plus.screen.unlockOrientation()
		plus.screen.lockOrientation('portrait-primary')
	}
	// onNavigationBarButtonTap: function (e) {
	// 	// e的返回格式为json对象：{"text":"测试","index":0}
	// 	switch (e.index) {
	// 		case 0:
	// 			document.getElementById('wrapper').toDataURL((res) => {
	// 				console.log(res)
	// 			})
	// 			// console.log('event', e)
	// 			break
	// 	}
	// }
}
</script>
<script module="canvasToImage" lang="renderjs">
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf'
export default {
	data() {
		return {}
	},
	methods: {
		// 获取设备的Dpr值
		getDpr() {
			if (window.devicePixelRatio && window.devicePixelRatio > 1) {
				return window.devicePixelRatio;
			}
			return 1;
		},
		/**
		 * 将传入值转为整数
		 * @param value
		 * @returns {number}
		 */
		parseValue(value) {
			return parseInt(value, 10);
		},

           // 截图后保存到本地
		generateImage(event, ownerInstance) {
			// 获取想要转换的dom节点
			var dom = document.getElementById('wrapper');
			html2canvas(dom, {
				// allowTaint: false,
				width: dom.clientWidth,
				height: dom.clientHeight,
				scrollY: 0,
				scrollX: 0,
				useCORS: true
			}).then(function(canvas) {
				var contentWidth = canvas.width; //所选元素宽度
						var contentHeight = canvas.height; //所选元素高度
						//一页pdf显示html页面生成的canvas高度;
						var pageHeight = contentWidth / 595.28 * 841.89;
						//未生成pdf的html页面高度
						var leftHeight = contentHeight;
						//pdf页面偏移
						var position = 0;
						//a4纸的尺寸[595.28,841.89]，html页面生成的canvas在pdf中图片的宽高
						var imgWidth = 555.28;
						var imgHeight = 555.28 / contentWidth * contentHeight;
						var pageData = canvas.toDataURL('image/jpeg', 1.0); //转成jpg格式
						var pdf = new jsPDF('', 'pt', 'a4'); //生成pdf实例
						//有两个高度需要区分，一个是html页面的实际高度，和生成pdf的页面高度(841.89)
						//当内容未超过pdf一页显示的范围，无需分页
						if (leftHeight < pageHeight) {
							pdf.addImage(pageData, 'JPEG', 20, 0, imgWidth, imgHeight);
						} else {
							while (leftHeight > 0) {
								pdf.addImage(pageData, 'JPEG', 20, position, imgWidth, imgHeight)
								leftHeight -= pageHeight;
								position -= 841.89;
								//避免添加空白页
								if (leftHeight > 0) {
									pdf.addPage();
								}
							}
						}

						var blob = pdf.output("datauristring");
                       console.log('start downloading')
                       ownerInstance.callMethod('downloadFile', blob)
			});
		},
	}
}
</script>
<style lang="scss" scoped>
.wrapper {
	display: flex;
	flex-direction: column;
}

.space-wrapper {
	margin-top: 20rpx;
}

.button {
	margin-top: 20rpx;
}
.danger {
	color: white;
	margin-top: 20rpx;
	background-color: #f56c6c;
	border-color: #f56c6c;
}
::v-deep .uni-card {
	overflow: unset !important;
}

.uni-list-cell {
	background-color: #fff;
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 20rpx 20rpx;
	.uni-list-cell-left {
		font-size: 35rpx;
	}
}
.uni-list-cell-db {
	flex: 1;
}
.as-input {
	width: 100%;
	border: solid 1px #e5e5e5;
	border-radius: 10rpx;
	padding: 20rpx 10rpx;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	.customer-icon {
		padding: 0 0 0 5rpx;
	}
	.placeholder {
		font-size: 33rpx;
		color: #999;
	}
	.as-content {
		color: #333;
		font-size: 33rpx;
		width: 370rpx;
		text-align: right;
	}
}

.image-category {
	width: 200rpx;
	height: 200rpx;
}
.content-wrap {
	padding: 20rpx;
	padding-bottom: 120rpx;
}
.bottom {
	height: 120rpx;
	width: 750rpx;
	position: fixed;
	bottom: 0;
	background-color: white;
	display: flex;
	padding: 0 30rpx;
	// justify-content: center;
	align-items: center;
	font-size: 35rpx;
	color: #333;
	text {
		color: #f56c6c;
		font-size: 40rpx;
		margin-left: 20rpx;
	}
}

.table-wrap {
	padding: 5rpx;
}

.custom-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 14px;
	background: #fff;
}
.custom-table th,
.custom-table td {
	border: 1px solid #222;
	padding: 6px 4px;
	text-align: center;
}
.custom-table .title {
	font-size: 18px;
	font-weight: bold;
	text-align: center;
	padding: 12px 0;
}
.custom-table .label {
	background: #f8f8f8;
	font-weight: bold;
	width: 80px;
}
.custom-table .value {
	text-align: left;
	padding-left: 8px;
}
.custom-table .green {
	color: green;
	font-weight: bold;
}
.custom-table .red {
	color: #e60012;
	font-weight: bold;
}
.custom-table .total {
	font-weight: bold;
	text-align: right;
	background: #f8f8f8;
}
.custom-table .note {
	font-size: 12px;
	text-align: left;
	padding: 8px;
	background: #fafafa;
}
.custom-table .center {
	text-align: center;
}

image {
	width: 100rpx;
	height: 100rpx;
}
</style>
